import UIKit

// 格
class Grid {
    public var mUsed: Bool  // 使用则为 true，否则为 false
    
    /**
     * 构造方法。
     */
    public init() {
        mUsed = false
    }
}

// 带颜色的格
class ColorGrid: Grid {
    public var mColor: CGColor! // 颜色
}

// 方块
class Block: NSObject {
    // 方块形状
    enum Shape {
        case ONE    // 形状1
        case TWO    // 形状2
        case THREE  // 形状3
        case FOUR   // 形状4
    }
    
    internal var mBlocks: [[Grid]]      // 方块数据
    internal let mColor: CGColor        // 颜色
    internal var mDrawer: CGContext!    // 绘图者
    private var mGameBoard: UIView!     // 游戏区域
    internal var mLine: Int             // 当前所在列(左)
    internal var mRow: Int              // 当前所在行(上)
    internal var mShape: Shape          // 形状

    /**
     * 构造方法。
     */
    public override init() {
        mBlocks = [[Grid]]()
        var gridArray: Array<Grid>!
        for _ in 0 ..< Const.BLOCK_GRID_COUNT_V {
            gridArray = Array<Grid>()
            for _ in 0 ..< Const.BLOCK_GRID_COUNT_H {
                gridArray.append(Grid())
            }
            mBlocks.append(gridArray)
        }

        let red = CGFloat(arc4random() % 256) / Const.WHITE
        let green = CGFloat(arc4random() % 256) / Const.WHITE
        let blue = CGFloat(arc4random() % 256) / Const.WHITE
        mColor = CGColor(red: red, green: green, blue: blue, alpha: 1.0)        
        mLine = 3
        mRow = -1
        mShape = .ONE
    }
    
    /**
     * 获取底端所在的行数。底端是指方块最下方的有效格。
     * @return 底端所在的行数
     */
    public var bottom: Int {
        get {
            return 0
        }
    }

    /**
     * 绘制自身。
     */
    public func draw() {
        var rect: CGRect!
        
        for i in 0 ..< Const.BLOCK_GRID_COUNT_H {
            for j in 0 ..< Const.BLOCK_GRID_COUNT_V {
                if !mBlocks[i][j].mUsed {
                    continue
                }

                let left = Const.GRID_SIZE * (mLine + j)
                let top = Const.GRID_SIZE * (mRow + i)
                rect = CGRect(x: left, y: top, width: Const.GRID_SIZE, height: Const.GRID_SIZE)
                mDrawer.setFillColor(mColor)
                mDrawer.fill(rect)
                Block.drawEdge(mDrawer, left: left, top: top)
            }
        }

        mGameBoard.setNeedsDisplay()
    }

    /*
     * 画矩形的边框，使矩形具有立体效果。
     * @param drawer    绘图者
     * @param left, top 矩形的左上角坐标
     */
    public static func drawEdge(_ drawer: CGContext, left: Int, top: Int) {
        let right = left + Const.GRID_SIZE - 1
        let bottom = top + Const.GRID_SIZE - 1

        var red = 214 / Const.WHITE
        var green = 211 / Const.WHITE
        var blue = 206 / Const.WHITE
        let colorLeftTop1 = CGColor(red: red, green: green, blue: blue, alpha: 1.0)
        let colorLeftTop2 = UIColor.white.cgColor

        red = 66 / Const.WHITE
        green = 65 / Const.WHITE
        blue = 66 / Const.WHITE
        let colorRightBottom1 = CGColor(red: red, green: green, blue: blue, alpha: 1.0)

        red = 132 / Const.WHITE
        green = 130 / Const.WHITE
        blue = 132 / Const.WHITE
        let colorRightBottom2 = CGColor(red: red, green: green, blue: blue, alpha: 1.0)
        
        var rect: CGRect!

        drawer.setFillColor(colorLeftTop1)
        rect = CGRect(x: left, y: top, width: Const.GRID_SIZE - 1, height: 1)
        drawer.fill(rect)
        rect = CGRect(x: left, y: top, width: 1, height: Const.GRID_SIZE - 1)
        drawer.fill(rect)

        drawer.setFillColor(colorLeftTop2)
        rect = CGRect(x: left + 1, y: top + 1, width: Const.GRID_SIZE - 3, height: 1)
        drawer.fill(rect)
        rect = CGRect(x: left + 1, y: top + 1, width: 1, height: Const.GRID_SIZE - 3)
        drawer.fill(rect)

        drawer.setFillColor(colorRightBottom1)
        rect = CGRect(x: right, y: top, width: 1, height: Const.GRID_SIZE)
        drawer.fill(rect)
        rect = CGRect(x: left, y: bottom, width: Const.GRID_SIZE - 1, height: 1)
        drawer.fill(rect)

        drawer.setFillColor(colorRightBottom2)
        rect = CGRect(x: right - 1, y: top + 1, width: 1, height: Const.GRID_SIZE - 2)
        drawer.fill(rect)
        rect = CGRect(x: left + 1, y: bottom - 1, width: Const.GRID_SIZE - 3, height: 1)
        drawer.fill(rect)
    }
    
    /**
     * 进入游戏区域。
     * @param gameBoard 游戏区域
     * @param drawer    绘图者
     */
    public func enterGameBoard(_ gameBoard: UIView, drawer: CGContext) {
        mGameBoard = gameBoard
        mDrawer = drawer
        self.draw()
    }
    
    /**
     * 进入预览区域。
     * @param preview   预览区域
     * @param drawer    绘图者
     */
    public func enterPreview(_ preview: UIView, drawer: CGContext) {
        let x = (Int(preview.frame.width) - Const.GRID_SIZE * 3) / 2
        let y = Int(preview.frame.height) / 2 - Const.GRID_SIZE * 2
        var rect: CGRect!
    
        // 遍历所有格，跳过无效的，画有效的
        for i in 0 ..< Const.BLOCK_GRID_COUNT_H {
            for j in 0 ..< Const.BLOCK_GRID_COUNT_V {
                if !mBlocks[i][j].mUsed {
                    continue
                }
                drawer.setFillColor(mColor)
                rect = CGRect(x: x + Const.GRID_SIZE * j, y: y + Const.GRID_SIZE * i, width: Const.GRID_SIZE, height: Const.GRID_SIZE)
                drawer.fill(rect)
                Block.drawEdge(drawer, left: x + Const.GRID_SIZE * j, top: y + Const.GRID_SIZE * i)
            }
        }
    }

    /**
     * 擦除。
     */
    internal func erase() {
    }
    
    /**
     * 擦除矩形。
     * @param rect  矩形
     */
    internal func eraseRect(_ rect: CGRect) {
        mDrawer.setFillColor(Const.GAME_BOARD_COLOR)
        mDrawer.fill(rect)
    }

    /**
     * 对不能下落的处理。
     */
    internal func handleCannotMoveDown() {
    }

    /**
     * 下落。
     * @return 总是 true
     */
    public func moveDown() -> Bool {
        self.erase()
        mRow += 1
        self.draw()

        return true
    }

    /**
     * 左移。
     */
    public func moveLeft() {
        self.erase()
        mLine -= 1
        self.draw()
    }

    /**
     * 右移。
     */
    public func moveRight() {
        self.erase()
        mLine += 1
        self.draw()
    }

    /**
     * 获取顶端所在的行数。顶端是指方块最上方的有效格。
     * @return 顶端所在的行数
     */
    public var top: Int {
        get {
            return 0
        }
    }

    /**
     * 变形。
     */
    public func transform() {
    }
}
